"""工具函数与通用响应封装。"""
from functools import wraps
import traceback
from typing import Any, Callable, TypeVar

from sqlalchemy.exc import InternalError

_F = TypeVar('_F', bound=Callable[..., Any])


def success_response(data=None, message='success', code=200):
    """成功响应（Flask-RESTful 直接返回字典）"""
    return {
        'code': code,
        'message': message,
        'data': data
    }, code


def error_response(message='error', code=400, data=None):
    """错误响应（Flask-RESTful 直接返回字典）"""
    return {
        'code': code,
        'message': message,
        'data': data
    }, code


def handle_errors(f: _F) -> _F:
    """异常处理装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        attempted_retry = False
        while True:
            try:
                return f(*args, **kwargs)
            except InternalError as err:
                msg = str(err)
                if (not attempted_retry) and ('Packet sequence number wrong' in msg):
                    attempted_retry = True
                    print(f"[handle_errors] {f.__name__} detected packet sequence error, attempting DB reconnect")
                    try:
                        try:
                            from .. import db  # type: ignore
                        except ImportError:  # pragma: no cover - fallback when running from server package root
                            from app import db  # type: ignore
                        db.session.remove()
                        db.engine.dispose()
                    except Exception as cleanup_err:  # pragma: no cover - defensive
                        print(f"[handle_errors] failed to reset DB engine: {cleanup_err}")
                    continue
                print(f"[handle_errors] {f.__name__} raised {err}")
                traceback.print_exc()
                return error_response(message=msg, code=500)
            except Exception as e:  # pragma: no cover - catch-all for API stability
                print(f"[handle_errors] {f.__name__} raised {e}")
                traceback.print_exc()
                return error_response(message=str(e), code=500)

    return decorated_function  # type: ignore[return-value]
